#include "gut/RenderTarget.h"

void Gut::RenderTarget::Create(const Gut::RenderTarget::Desc &desc)
{
    mWidth = desc.width;
    mHeight = desc.height;

    frameBuffer.Create();

    texDesc.target = desc.target;
    texDesc.width = desc.width;
    texDesc.height = desc.height;
    texDesc.internalformat = desc.internalFormat;
    texDesc.format = desc.format;
    texDesc.data = 0;
    texDesc.dataType = desc.dataType;

    std::vector<unsigned int> attachments;

    for (int i = 0; i < desc.numTexture; i++)
    {
        Texture2D outColor;
        outColor.Create();
        outColor.TexImage2D(texDesc);
        outColor.Bind();

        SamplerDesc samDesc;
        samDesc.minFilter = GL_LINEAR;
        samDesc.magFilter = GL_LINEAR;

        outColor.SetSampler(samDesc);
        outColor.Mipmap();

        frameBuffer.BufferTexture2D(GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, outColor.ID);
        attachments.emplace_back(GL_COLOR_ATTACHMENT0 + i);

        outColors.emplace_back(outColor);
    }

    depthDesc.target = desc.target;
    depthDesc.width = desc.width;
    depthDesc.height = desc.height;
    depthDesc.internalformat = GL_DEPTH_COMPONENT;
    depthDesc.format = GL_DEPTH_COMPONENT;
    depthDesc.dataType = desc.dataType;
    depthDesc.data = 0;

    depthMap.Create();
    depthMap.TexImage2D(depthDesc);
    SamplerDesc samDesc;
    samDesc.minFilter = GL_NEAREST;
    samDesc.magFilter = GL_NEAREST;
    samDesc.wrapS = GL_CLAMP_TO_EDGE;
    samDesc.wrapT = GL_CLAMP_TO_EDGE;
    samDesc.useBorderColor = true;
    samDesc.borderColor[0] = 1.0f;
    samDesc.borderColor[1] = 1.0f;
    samDesc.borderColor[2] = 1.0f;
    samDesc.borderColor[3] = 1.0f;
    depthMap.SetSampler(samDesc);

    attachments.emplace_back(GL_DEPTH_ATTACHMENT);

    frameBuffer.DrawBuffers(&attachments[0], attachments.size());

    rBuffer.Create();
    rBuffer.Storage(GL_DEPTH24_STENCIL8, desc.width, desc.height);
    frameBuffer.FrameRenderBuffer(GL_DEPTH_STENCIL_ATTACHMENT, rBuffer.ID);
    frameBuffer.CheckError();
}

void Gut::RenderTarget::SetWindowSize(int width, int height)
{
    if (texDesc.width == width && texDesc.height == height)
    {
        return;
    }

    texDesc.width = width;
    texDesc.height = height;

    for (auto &outColor : outColors)
    {
        outColor.TexImage2D(texDesc);
    }
    depthDesc.width = width;
    depthDesc.height = height;
    depthMap.TexImage2D(depthDesc);

    rBuffer.Storage(GL_DEPTH24_STENCIL8, width, height);

    mWidth = width;
    mHeight = height;
}